﻿using System;
using System.Collections.Generic;
using System.Diagnostics;

using agree.configuration;
using agree.schema;

namespace agree
{
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// cross-cutting general-purpose interfaces
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public interface ISourceWord : IString, ρρSourceCharacterStart, ρρSourceCharacterEnd, ρρSurfaceForm
	{
	};
	public interface IWordToken : ISourceWord, ρρTokenSpan
	{
	};
	public interface IItem : IString, ρρItemStatus, ρρTranslation, ρρExpectedDerivationCount
	{
	};

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// Interface for a tokenizer which is able to report multiple arbitrarily overlapping tokenization hypotheses. The
	/// design currently assumes that each non-overlapping permutation that does not exclude any unblocked tokens is a
	/// distinct hypothesis. Under such a scheme, it is possible for some hypotheses to not consume some character 
	/// positions which are used in other hypotheses.
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public interface ITokenizer : IIdentity
	{
		IEnumerable<ICharacterSpan> Tokenize(String s_input);
		String DefaultWordBreak { get; }
		String MakeSurface(IEnumerable<String> words);
	};

	public interface ICharacterSpan : IIdentity, ρρText
	{
		ChartSpan CharacterSpan { get; }
	};

	public interface ITokenSpan : ICharacterSpan
	{
		ChartSpan TokenSpan { get; }
	};

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// interfaces for grammar entities
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	/// <summary> grammar entity that may have a constraint definition and (expanded) typed feature structure. 
	/// This includes all types from the type hierarchy, even if unconstrained, as well as 'entries' </summary>
	public interface IInstance : IIdentityId, ρρName
	{
		Tfs Expanded { get; }
		Tfs Definition { get; }
	};

	/// <summary> in DELPH-IN nomenclature, an 'Entry' is a licensing entry point into the grammar. This includes
	/// lexical entries, various rule types, and start symbols.</summary>
	public interface IEntry : IInstance
	{
		Type InstanceType { get; }
		EntryMgr EntryMgr { get; }
	};

	/// <summary> entries that can reside in a parse or generation chart must have daughter arity. These include 
	/// lexical entries (arity zero) and rules (syntax, lexical, morphological) </summary>
	public interface IChartLicense : IEntry
	{
		int DaughterArity { get; }
	};
	public interface ILexical : IChartLicense
	{
	};
	public interface ILexeme : ILexical, ρρTokenizer
	{
		String ReadbackTokensForm(ITfsSlot ts);
		String ReferenceForm { get; }
	};


	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// interfaces for operational (runtime) entities
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	/// <summary> interface for a grammar rule which might be skolemized </summary>
	public interface IActiveRule : IIdentity
	{
		Rule BaseRule { get; }
		TfsSlot[] DaughterNodes { get; }
	};

	public interface IUnificationController : IRtParent, ρρQuickCheck, ρρTfsUnifier
	{
	};

	public interface IChartControl : IUnificationController
	{
		PackedForest Forest { get; }
		void Wait();
		bool IsSpanning(IChartObj co);
		int SpanningCount { get; }
		IEnumerable<IChartObj> AllEdges();
	};

	public interface IProximalContext<W>
		where W : struct
	{
		int CoverageCount { get; }
		bool CombineWith(W other, out W result);
		bool CanCombineWith(W other);
	};

	public interface IChartObj : IDerivation, IAtomicSequence, ITfsSlot
	{
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		IChartObj Next { get; }

		bool TrySetNext(IChartObj po_to_set, IChartObj po_expected);

		IChartObj AddToList(IChartObj po_to_add, ref long next_id);

		int CoverageCount { get; }
	};

	public interface IChartObj<W> : IChartObj
		where W : struct, IProximalContext<W>
	{
		W ProximalContext { get; }
	};

	public interface IDerivation : IIdentity, ρρParseSelectionScore, ρρItemStartSymbol
	{
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		IChartLicense ChartLicense { get; }

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		IReadOnlyList<IDerivation> Daughters { get; }

		Tfs DerivationTfs();

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		ulong DerivationHash { get; }

		Double Score(MaxEntModel model);

		StartSymbol[] MatchedStartSymbols { get; }
	};

	public interface ILexicalDerivation : ILexical, IDerivation
	{
	};
}
